home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 3 / CD ACTUAL 3.iso / linux / sonido / sfxserve.000 / sfxserve / sfxserver-0.02 / mix.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-10  |  4.5 KB  |  146 lines

  1. /*
  2.  * ---------------------------------------------------------------------------
  3.  * sfxserver/mix.c
  4.  *
  5.  * Copyright by Terry Evans 1994
  6.  * tevans@cs.utah.edu, tevans@slc.unisys.com
  7.  * ---------------------------------------------------------------------------
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions are
  11.  * met: 1. Redistributions of source code must retain the above copyright
  12.  * notice, this list of conditions and the following disclaimer. 2.
  13.  * Redistributions in binary form must reproduce the above copyright notice,
  14.  * this list of conditions and the following disclaimer in the documentation
  15.  * and/or other materials provided with the distribution.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
  18.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20.  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
  21.  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27.  * SUCH DAMAGE.
  28.  * ---------------------------------------------------------------------------
  29.  */
  30.  
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <sys/types.h>
  35. #include <unistd.h>
  36.  
  37.  
  38. #include "global.h"
  39. #include "types.h"
  40. #include "channel.h"
  41. #include "io.h"
  42. #include "error.h"
  43.  
  44.  
  45. /* From channel.c */
  46. extern int channel_number;
  47.  
  48.  
  49. void M_Init(mix_t *mix, int frag_size)
  50. {
  51.   IO_WriteStdout("        Setting up mix data structure\n");
  52.  
  53.   if((mix->clipped = (unsigned char *)calloc(sizeof(char), frag_size)) == NULL)
  54.     E_FatalError("M_Init", "Unable to calloc clipped buffer");
  55.  
  56.   if((mix->silence = (unsigned char *)calloc(sizeof(char), frag_size)) == NULL)
  57.     E_FatalError("M_Init", "Unable to calloc silence buffer");
  58.  
  59.   /* Set the silence to be silent */
  60.   memset(mix->silence, 128, frag_size);
  61.  
  62.   mix->size = frag_size;
  63. }
  64.  
  65.  
  66. void M_DeInit(mix_t *mix)
  67. {
  68.   if(mix->clipped != NULL)
  69.     free(mix->clipped);
  70. }
  71.  
  72.  
  73. void M_MixChannels(mix_t *mix, channel_t **channel, int frag_size, int s_fd, int stereo)
  74. {
  75.   int loop;
  76.   int frag_offset;
  77.   int num_channels_in_use;
  78.   char data;
  79.  
  80.   /* This is so it isn't recalc'd at each iteration of the loop */
  81.   int half_frag = frag_size >> 1;
  82.  
  83.   /* We are only doing a half a frag at a time */
  84.   /* This is for stereo output */
  85.   for(frag_offset = 0; frag_offset < half_frag; frag_offset++)
  86.   {
  87.     mix->unclipped_l = 0;
  88.     mix->unclipped_r = 0;
  89.     num_channels_in_use = 0;
  90.  
  91.     /* channel_number is the maximum channel number allocated so far */
  92.     for(loop = 0; loop < channel_number; loop++)
  93.     {
  94.       /* See if it is a free channel */
  95.       if(channel[loop] != NULL)
  96.       {
  97.     /* See if the channel is in use */
  98.         if(channel[loop]->in_use)
  99.         {
  100.       /* Normalize the data */
  101.           data = (*(channel[loop]->sample->data + channel[loop]->position)) ^ 0x80;
  102.       mix->unclipped_l += channel[loop]->vol_left * (float)data;
  103.       mix->unclipped_r += channel[loop]->vol_right * (float)data;
  104.  
  105.       num_channels_in_use++;
  106.  
  107.       /* Increment to the next byte of sound to read in */
  108.       /* See if this sample is done being played */
  109.       if(++channel[loop]->position >= channel[loop]->sample->length)
  110.         channel[loop]->in_use = FALSE;
  111.         }
  112.       }
  113.     }
  114.  
  115.     /* If there is nothing to play, just write out silence */
  116.     if(num_channels_in_use == 0)
  117.     {
  118.       write(s_fd, mix->silence, frag_size);
  119.       return;
  120.     }
  121.  
  122.     /* Re-normalize the values */
  123.     mix->unclipped_l += 128;
  124.     mix->unclipped_r += 128;
  125.  
  126.     /* Left Channel */
  127.     if(mix->unclipped_l < 0)
  128.       mix->clipped[frag_offset << 1] = 0;
  129.     else if(mix->unclipped_l > 255)
  130.       mix->clipped[frag_offset << 1] = 255;
  131.     else
  132.       mix->clipped[frag_offset << 1] = mix->unclipped_l;
  133.  
  134.     /* Rigt Channel */
  135.     if(mix->unclipped_r < 0)
  136.       mix->clipped[(frag_offset << 1) + 1] = 0;
  137.     else if(mix->unclipped_r > 255)
  138.       mix->clipped[(frag_offset << 1) + 1] = 255;
  139.     else
  140.       mix->clipped[(frag_offset << 1) + 1] = mix->unclipped_r;
  141.   }
  142.  
  143.   /* Write out the data */
  144.   write(s_fd, mix->clipped, frag_size);
  145. }
  146.